feat(core,html,react): vimeo provider with configurable embed params#1538
feat(core,html,react): vimeo provider with configurable embed params#1538ronald-urbina wants to merge 9 commits into
Conversation
…and privacy defaults
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✅ Deploy Preview for vjs10-site ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📦 Bundle Size Report🎨 @videojs/html
Presets (7)
Media (9)
Players (5)
Skins (30)
UI Components (34)
Sizes are marginal over the root entry point. ⚛️ @videojs/react
Presets (7)
Media (8)
Skins (27)
UI Components (27)
Sizes are marginal over the root entry point. 🧩 @videojs/core
Entries (10)
🏷️ @videojs/element — no changesEntries (2)
📦 @videojs/store — no changesEntries (3)
🔧 @videojs/utils — no changesEntries (10)
📦 @videojs/spf — no changesEntries (3)
ℹ️ How to interpretAll sizes are standalone totals (minified + brotli).
Run |
…rom preset filter
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 14ac63f. Configure here.
|
|
||
| set volume(value: number) { | ||
| this.#player?.setVolume(value); | ||
| } |
There was a problem hiding this comment.
Volume setter doesn't update cached value immediately
Medium Severity
The volume setter calls setVolume on the SDK but doesn't update #volume locally, so media.volume returns a stale value until the async volumechange event fires. The playbackRate setter has the same issue. This is inconsistent with other setters like muted, loop, autopause, color, and quality, which all update their local cache immediately. It also differs from HTMLVideoElement behavior where the getter reflects the set value synchronously.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 14ac63f. Configure here.
| iframe?.focus(); | ||
| }; | ||
| globalThis.document?.addEventListener('click', focusIframe, { capture: true }); | ||
| this.#activationCleanup = () => globalThis.document?.removeEventListener('click', focusIframe, { capture: true }); |
There was a problem hiding this comment.
Global click listener steals focus on every click
Medium Severity
The focusIframe handler added in attach() listens for every click on document in the capture phase and calls iframe.focus(), which changes document.activeElement to the iframe. This steals focus from whatever the user actually clicked on — interactive elements like inputs get refocused by the browser's default behavior (causing a focus flicker with extra focusin/focusout events), while non-standard focusable elements may permanently lose focus. The listener also runs on all browsers even though its purpose (PiP user activation) is Safari-only per isPipCapable.
Reviewed by Cursor Bugbot for commit 14ac63f. Configure here.


Closes #1435
Summary
Implements the Vimeo provider across
core,html, andreactpackages.VimeoMedia(core/dom) — Headless media engine adapter backed by@vimeo/player. ImplementsMediaEngineHost,MediaPictureInPictureCapability, andMediaTextTrackCapability. Exposes the full Vimeo embed parameter surface (dnt,byline,portrait,title,color,autopause,background,loop,muted,responsive,speed,texttrack,transparent,quality,playsinline,controls). Defaultsdnt: truefor GDPR compliance out of the box.VimeoVideo(html) — Custom element wrappingVimeoMedia. All embed params are reflected as HTML attributes. Ships a CDN-ready define entry and registers withcustomElementsviadefine/media/vimeo-video.ts.VimeoVideo(react) —forwardRefcomponent. Accepts all embed params as props; syncs them to the underlyingVimeoMediainstance viauseSyncProps. Renders adivcontainer thatVimeoMediatargets (not a native<video>element).PiP — Safari-only via WebKit's cross-origin iframe mechanism; flagged via
isPipCapableon the adapter.Sandbox — Vimeo source wired into the dev playground for manual testing.
Skins — CSS updated so the Vimeo iframe fills the player container consistently in both
defaultandminimalthemes.Test plan
pnpm -F @videojs/core test src/dom/media/vimeo— unit tests passpnpm typecheck— no type errorspnpm -F sandbox dev— load a Vimeo source in the sandbox, verify play/pause/seek/mute/volume/duration/ended eventsdnt=trueis sent in the embed URL by default (check Network tab iframe src)dnt,byline,portrait,titleattributes in DevTools and confirm the player reinitializes with updated paramsNote
High Risk
Adds a new cross-origin iframe-backed media engine (
VimeoMedia) plus updates Picture-in-Picture availability/exit logic, which can affect core playback/event behavior across players. Integration relies on the external@vimeo/playerSDK and new state/event mappings, increasing surface area for regressions.Overview
Adds first-class Vimeo playback support by introducing
VimeoMediain@videojs/core(backed by@vimeo/player) with event/state bridging, configurable embed parameters, text track support, and Safari-only PiP signaling.Exposes the provider via new HTML custom element
vimeo-video(including CDN define entry) and a new ReactVimeoVideocomponent that syncs props to the underlying engine.Updates PiP detection/exit to consider media-specific capability (
isPipCapableand provider-levelexitPictureInPicture), adds unit tests for both PiP gating and the new Vimeo engine, and extends the sandbox (newvimeo-videopreset, Vimeo sources, and HTML/React templates) plus skin CSS/Tailwind tweaks so Vimeo embeds size correctly.Reviewed by Cursor Bugbot for commit 14ac63f. Bugbot is set up for automated code reviews on this repo. Configure here.